﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Transfer.Utils;

namespace Transfer.CrossDocument
{
	public class ElementSelector
	{
		public List<string> CheckedCategoryNames
		{
			set
			{
				this.m_CheckedCategoryNames = value;
			}
		}

		public ElementSelector(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
		}

		public List<string> GetAllTypeNames(Autodesk.Revit.DB.Document sourceDocument)
		{
			this.m_SourceDocument = sourceDocument;
			this.m_CheckedCategoryNames.Clear();
			List<string> result = new List<string>();
			this.GetTransformElementsIdList(sourceDocument, true, ref result);
			return result;
		}

		public void GetTransformElementsIdList(Autodesk.Revit.DB.Document sourceDocument, bool getAll)
		{
			List<string> list = new List<string>();
			this.GetTransformElementsIdList(sourceDocument, getAll, ref list);
		}

		public bool FindCopyTypeByName(string findName)
		{
			return this.m_CheckedCategoryNames.FindIndex((string name) => name.CompareTo(findName) == 0) >= 0;
		}

		private void GetTransformElementsIdList(Autodesk.Revit.DB.Document sourceDocument, bool getAll, ref List<string> typeNameList)
		{
			this.m_SourceDocument = sourceDocument;
			this.ClearElementsList();
			bool copyWall = true;
			if (!this.FindCopyTypeByName("Walls") && !this.FindCopyTypeByName("墙"))
			{
				copyWall = false;
			}
			Options options = this.m_Revit.Application.Application.Create.NewGeometryOptions();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_SourceDocument);
			filteredElementCollector.WhereElementIsNotElementType();
			foreach (Element element in filteredElementCollector.ToElements())
			{
				if (!(element is FamilySymbol) && !(element is Level) && element.Category != null && element.Location != null && !(null == element.get_Geometry(options)) && !(null == element.GetTypeId()) && !(element.GetTypeId() == ElementId.InvalidElementId))
				{
					string categoryName = element.Category.Name;
					if ((getAll || this.m_CheckedCategoryNames.FindIndex((string name) => name.CompareTo(categoryName) == 0) >= 0) && this.FilterTransformElement(copyWall, element) && getAll && typeNameList.FindIndex((string name) => name.CompareTo(categoryName) == 0) < 0)
					{
						typeNameList.Add(categoryName);
					}
				}
			}
		}

		public void GetGeneralElementsIdList(ref List<List<ElementId>> generalElementsIdList)
		{
			generalElementsIdList.Add(this.m_WallGeneralElementsIdList);
			generalElementsIdList.Add(this.m_CeilingGeneralElementsIdList);
			generalElementsIdList.Add(this.m_FloorGeneralElementsIdList);
			generalElementsIdList.Add(this.m_RailingGeneralElementsIdList);
			generalElementsIdList.Add(this.m_StairsGeneralElementsIdList);
			generalElementsIdList.Add(this.m_GroupGeneralElementsIdList);
			generalElementsIdList.Add(this.m_RevitLinkInstanceGeneralElementsIdList);
			generalElementsIdList.Add(this.m_OpeningGeneralElementsIdList);
			generalElementsIdList.Add(this.m_TextNoteGeneralElementsIdList);
			generalElementsIdList.Add(this.m_RoomGeneralElementsIdList);
			generalElementsIdList.Add(this.m_RoomTagGeneralElementsIdList);
			generalElementsIdList.Add(this.m_SpaceGeneralElementsIdList);
			generalElementsIdList.Add(this.m_SpaceTagGeneralElementsIdList);
			generalElementsIdList.Add(this.m_ZoneGeneralElementsIdList);
			generalElementsIdList.Add(this.m_IndependentTagGeneralElementsIdList);
			generalElementsIdList.Add(this.m_AreaGeneralElementsIdList);
			generalElementsIdList.Add(this.m_AreaTagGeneralElementsIdList);
			generalElementsIdList.Add(this.m_DimensionGeneralElementsIdList);
			this.MepSystemGrouping(this.m_PipeGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			this.MepSystemGrouping(this.m_FlexPipeGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			this.MepSystemGrouping(this.m_DuctGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			this.MepSystemGrouping(this.m_FlexDuctGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			this.ElectricSystemGrouping(this.m_CableTrayGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			this.ElectricSystemGrouping(this.m_ConduitGeneralElementsIdList, ref generalElementsIdList, ref this.m_InstanceGeneralElementsIdList);
			generalElementsIdList.Add(this.m_InstanceGeneralElementsIdList);
		}

		private void MepSystemGrouping(List<ElementId> MEPCurveIdList, ref List<List<ElementId>> generalElementsIdList, ref List<ElementId> instanceIdList)
		{
			Document sourceDocument = this.m_SourceDocument;
			Dictionary<ElementId, List<ElementId>> dictionary = new Dictionary<ElementId, List<ElementId>>();
			foreach (ElementId elementId in MEPCurveIdList)
			{
				Element element = sourceDocument.GetElement(elementId);
				ElementId id;
				if (element.GetType() == typeof(Pipe))
				{
					id = (element as Pipe).MEPSystem.Id;
				}
				else if (element.GetType() == typeof(FlexPipe))
				{
					id = (element as FlexPipe).MEPSystem.Id;
				}
				else if (element.GetType() == typeof(Duct))
				{
					id = (element as Duct).MEPSystem.Id;
				}
				else
				{
					if (!(element.GetType() == typeof(FlexDuct)))
					{
						continue;
					}
					id = (element as FlexDuct).MEPSystem.Id;
				}
				if (!dictionary.ContainsKey(id))
				{
					dictionary.Add(id, new List<ElementId>
					{
						elementId
					});
				}
				else
				{
					dictionary[id].Add(elementId);
				}
			}
			for (int i = 0; i < instanceIdList.Count; i++)
			{
				ElementId elementId2 = instanceIdList[i];
				FamilyInstance familyInstance = sourceDocument.GetElement(elementId2) as FamilyInstance;
				if (familyInstance.MEPModel != null && familyInstance.MEPModel.ConnectorManager != null)
				{
					ConnectorSetIterator connectorSetIterator = familyInstance.MEPModel.ConnectorManager.Connectors.ForwardIterator();
					connectorSetIterator.MoveNext();
					try
					{
						ElementId id2 = (connectorSetIterator.Current as Connector).MEPSystem.Id;
						if (dictionary.ContainsKey(id2))
						{
							dictionary[id2].Add(elementId2);
							instanceIdList.RemoveAt(i);
							i--;
						}
					}
					catch (Exception)
					{
					}
				}
			}
			List<List<ElementId>> collection = dictionary.Values.ToList<List<ElementId>>();
			generalElementsIdList.AddRange(collection);
		}

		private void ElectricSystemGrouping(List<ElementId> MEPCurveIdList, ref List<List<ElementId>> generalElementsIdList, ref List<ElementId> instanceIdList)
		{
			Document sourceDocument = this.m_SourceDocument;
			new List<List<ElementId>>();
			for (int i = 0; i < MEPCurveIdList.Count; i++)
			{
				ElementId elementId = MEPCurveIdList[i];
				CableTrayConduitBase cableTrayConduitBase = sourceDocument.GetElement(elementId) as CableTrayConduitBase;
				List<ElementId> list = new List<ElementId>();
				list.Add(elementId);
				ConnectorSetIterator connectorSetIterator = cableTrayConduitBase.ConnectorManager.Connectors.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					object obj = connectorSetIterator.Current;
					Connector otherConnector = obj as Connector;
					this.GetCableTrayConduitConnectElements(cableTrayConduitBase, otherConnector, ref MEPCurveIdList, ref instanceIdList, ref list);
				}
				generalElementsIdList.Add(list);
			}
		}

		private void GetCableTrayConduitConnectElements(CableTrayConduitBase cableTrayConduit, Connector otherConnector, ref List<ElementId> cableTrayConduitIdList, ref List<ElementId> instanceIdList, ref List<ElementId> group)
		{
			ConnectorSetIterator connectorSetIterator = cableTrayConduit.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (!Geometry.IsEqual(connector.Origin, otherConnector.Origin))
				{
					ConnectorSetIterator connectorSetIterator2 = connector.AllRefs.ForwardIterator();
					while (connectorSetIterator2.MoveNext())
					{
						object obj2 = connectorSetIterator2.Current;
						Connector connector2 = obj2 as Connector;
						Element owner = connector2.Owner;
						if (owner.Id.IntegerValue != cableTrayConduit.Id.IntegerValue)
						{
							group.Add(owner.Id);
							if (owner.GetType() == typeof(FamilyInstance))
							{
								this.FindAndDeleteElement(owner.Id, ref instanceIdList);
								this.GetFamilyInstanceConnectElements(owner as FamilyInstance, connector2, ref cableTrayConduitIdList, ref instanceIdList, ref group);
							}
							else
							{
								this.FindAndDeleteElement(owner.Id, ref cableTrayConduitIdList);
								this.GetCableTrayConduitConnectElements(owner as CableTrayConduitBase, connector2, ref cableTrayConduitIdList, ref instanceIdList, ref group);
							}
						}
					}
				}
			}
		}

		private void GetFamilyInstanceConnectElements(FamilyInstance instance, Connector otherConnector, ref List<ElementId> cableTrayConduitIdList, ref List<ElementId> instanceIdList, ref List<ElementId> group)
		{
			ConnectorSetIterator connectorSetIterator = instance.MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (!Geometry.IsEqual(connector.Origin, otherConnector.Origin))
				{
					ConnectorSetIterator connectorSetIterator2 = connector.AllRefs.ForwardIterator();
					while (connectorSetIterator2.MoveNext())
					{
						object obj2 = connectorSetIterator2.Current;
						Connector connector2 = obj2 as Connector;
						Element owner = connector2.Owner;
						if (owner.Id.IntegerValue != instance.Id.IntegerValue)
						{
							group.Add(owner.Id);
							if (owner.GetType() == typeof(FamilyInstance))
							{
								this.FindAndDeleteElement(owner.Id, ref instanceIdList);
								this.GetFamilyInstanceConnectElements(owner as FamilyInstance, connector2, ref cableTrayConduitIdList, ref instanceIdList, ref group);
							}
							else
							{
								this.FindAndDeleteElement(owner.Id, ref cableTrayConduitIdList);
								this.GetCableTrayConduitConnectElements(owner as CableTrayConduitBase, connector2, ref cableTrayConduitIdList, ref instanceIdList, ref group);
							}
						}
					}
				}
			}
		}

		private void FindAndDeleteElement(ElementId id, ref List<ElementId> elementIdList)
		{
			int num = elementIdList.FindIndex((ElementId value) => value.IntegerValue == id.IntegerValue);
			if (num != -1)
			{
				elementIdList.RemoveAt(num);
			}
		}

		public void GetManualCopyEntitiesList(ref List<FamilyInstance> baseOnWallParasticElements, ref List<FamilyInstance> baseOnCeilingParasticElements, ref List<FamilyInstance> baseOnSurfaceParasticElements, ref List<Element> wiresList)
		{
			baseOnWallParasticElements = this.m_BaseOnWallParasticElements;
			baseOnCeilingParasticElements = this.m_BaseOnCeilingParasticElements;
			baseOnSurfaceParasticElements = this.m_BaseOnSurfaceParasticElements;
			wiresList = this.m_WiresList;
		}

		private bool FilterTransformElement(bool copyWall, Element currentElement)
		{
			if (currentElement.GetType() == typeof(FamilyInstance))
			{
				if (!this.FilterFamilyInstance(copyWall, currentElement as FamilyInstance))
				{
					return false;
				}
			}
			else if (!this.FilterNonFamilyInstance(currentElement))
			{
				return false;
			}
			return true;
		}

		private bool FilterFamilyInstance(bool copyWall, FamilyInstance familyInstance)
		{
			if (familyInstance.Host == null)
			{
				this.m_InstanceGeneralElementsIdList.Add(familyInstance.Id);
				return true;
			}
			if (familyInstance.Category.Id.IntegerValue == -2000023 || familyInstance.Category.Id.IntegerValue == -2000014 || familyInstance.Category.Name.CompareTo("Generic Models") == 0)
			{
				if (!copyWall)
				{
					this.m_BaseOnWallParasticElements.Add(familyInstance);
					return true;
				}
				return false;
			}
			else
			{
				Parameter parameter = familyInstance.Symbol.Family.get_Parameter(BuiltInParameter.FAMILY_HOSTING_BEHAVIOR);
				if (parameter == null)
				{
					return false;
				}
				int num = parameter.AsInteger();
				if (num == 0)
				{
					this.m_InstanceGeneralElementsIdList.Add(familyInstance.Id);
				}
				else if (num == 1)
				{
					this.m_BaseOnWallParasticElements.Add(familyInstance);
				}
				else if (num == 3)
				{
					this.m_BaseOnCeilingParasticElements.Add(familyInstance);
				}
				else if (num == 5)
				{
					this.m_BaseOnSurfaceParasticElements.Add(familyInstance);
				}
				else
				{
					this.m_InstanceGeneralElementsIdList.Add(familyInstance.Id);
				}
				return true;
			}
		}

		private bool FilterNonFamilyInstance(Element currentElement)
		{
			if (currentElement.GetType() == typeof(Railing))
			{
				this.m_RailingGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Stairs))
			{
				this.m_StairsGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Dimension))
			{
				this.m_DimensionGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Autodesk.Revit.DB.Group))
			{
				this.m_GroupGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(RevitLinkInstance))
			{
				this.m_RevitLinkInstanceGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Opening))
			{
				this.m_OpeningGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(TextNote))
			{
				this.m_TextNoteGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Wall))
			{
				this.m_WallGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Ceiling))
			{
				this.m_CeilingGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Floor))
			{
				this.m_FloorGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Room))
			{
				this.m_RoomGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(RoomTag))
			{
				this.m_RoomTagGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Space))
			{
				this.m_SpaceGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(SpaceTag))
			{
				this.m_SpaceTagGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Zone))
			{
				this.m_ZoneGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(IndependentTag))
			{
				this.m_IndependentTagGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Area))
			{
				this.m_AreaGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(AreaTag))
			{
				this.m_AreaTagGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Pipe))
			{
				this.m_PipeGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(FlexPipe))
			{
				this.m_FlexPipeGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Duct))
			{
				this.m_DuctGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(FlexDuct))
			{
				this.m_FlexDuctGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(CableTray))
			{
				this.m_CableTrayGeneralElementsIdList.Add(currentElement.Id);
			}
			else if (currentElement.GetType() == typeof(Conduit))
			{
				this.m_ConduitGeneralElementsIdList.Add(currentElement.Id);
			}
			else
			{
				if (!(currentElement.GetType() == typeof(Wire)))
				{
					return false;
				}
				this.m_WiresList.Add(currentElement);
			}
			return true;
		}

		private void ClearElementsList()
		{
			this.m_WallGeneralElementsIdList.Clear();
			this.m_CeilingGeneralElementsIdList.Clear();
			this.m_FloorGeneralElementsIdList.Clear();
			this.m_InstanceGeneralElementsIdList.Clear();
			this.m_RailingGeneralElementsIdList.Clear();
			this.m_StairsGeneralElementsIdList.Clear();
			this.m_GroupGeneralElementsIdList.Clear();
			this.m_RevitLinkInstanceGeneralElementsIdList.Clear();
			this.m_OpeningGeneralElementsIdList.Clear();
			this.m_TextNoteGeneralElementsIdList.Clear();
			this.m_RoomGeneralElementsIdList.Clear();
			this.m_RoomTagGeneralElementsIdList.Clear();
			this.m_SpaceGeneralElementsIdList.Clear();
			this.m_SpaceTagGeneralElementsIdList.Clear();
			this.m_ZoneGeneralElementsIdList.Clear();
			this.m_IndependentTagGeneralElementsIdList.Clear();
			this.m_AreaGeneralElementsIdList.Clear();
			this.m_AreaTagGeneralElementsIdList.Clear();
			this.m_PipeGeneralElementsIdList.Clear();
			this.m_FlexPipeGeneralElementsIdList.Clear();
			this.m_DuctGeneralElementsIdList.Clear();
			this.m_FlexDuctGeneralElementsIdList.Clear();
			this.m_CableTrayGeneralElementsIdList.Clear();
			this.m_ConduitGeneralElementsIdList.Clear();
			this.m_DimensionGeneralElementsIdList.Clear();
			this.m_BaseOnWallParasticElements.Clear();
			this.m_BaseOnCeilingParasticElements.Clear();
			this.m_BaseOnSurfaceParasticElements.Clear();
			this.m_WiresList.Clear();
		}

		private ExternalCommandData m_Revit;

		private Document m_SourceDocument;

		private List<ElementId> m_InstanceGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_RailingGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_StairsGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_DimensionGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_GroupGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_RevitLinkInstanceGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_OpeningGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_TextNoteGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_WallGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_CeilingGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_FloorGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_RoomGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_RoomTagGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_SpaceGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_SpaceTagGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_ZoneGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_IndependentTagGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_AreaGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_AreaTagGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_PipeGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_FlexPipeGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_DuctGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_FlexDuctGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_CableTrayGeneralElementsIdList = new List<ElementId>();

		private List<ElementId> m_ConduitGeneralElementsIdList = new List<ElementId>();

		private List<FamilyInstance> m_BaseOnWallParasticElements = new List<FamilyInstance>();

		private List<FamilyInstance> m_BaseOnCeilingParasticElements = new List<FamilyInstance>();

		private List<FamilyInstance> m_BaseOnSurfaceParasticElements = new List<FamilyInstance>();

		private List<Element> m_WiresList = new List<Element>();

		private List<string> m_CheckedCategoryNames = new List<string>();
	}
}
